﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Configuration;
using System.DirectoryServices.AccountManagement;
using System.DirectoryServices;

/// <summary>
/// Summary description for ActiveDirectory
/// </summary>
public class ActiveDirectory : Connector
{
    //maybe just copy LDAP
    //must test it
    string Domain;
    public ActiveDirectory()
    {
        GetSettingsFromConfig();
        Domain = ConfigurationManager.AppSettings["Domain"];
        GetPropertiesFromConfig();
        Users = new List<object>();
    }
    public ActiveDirectory(string log,string pas,string domain)
    {
        Login = log;
        Password = pas;
        Domain = domain;
        GetPropertiesFromConfig();
        Users = new List<object>();
    }

    public override dynamic GetConnect()
    {
        var context = new PrincipalContext(ContextType.Domain, Domain,"container", Login, Password);
        var searcher = new PrincipalSearcher(new UserPrincipal(context));
        
        return searcher;
    }
    public override List<dynamic> GetUsers()
    {
         if(String.IsNullOrEmpty(Login)||String.IsNullOrEmpty(Password)||String.IsNullOrEmpty(Domain))
         {
             Domain = ConfigurationManager.AppSettings["Domain"];
             GetSettingsFromConfig();
         }
         if (String.IsNullOrEmpty(Login) || String.IsNullOrEmpty(Password) || String.IsNullOrEmpty(Domain))
         {
             return null;
         } 
         var searcher = (GetConnect() as PrincipalSearcher);
         foreach (var result in searcher.FindAll())
         {
             //если у пользователя есть имя и аккаунт нейм
             if (result != null && result.DisplayName != null && result.SamAccountName != null)
             { 
                 DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
                 de.AuthenticationType = AuthenticationTypes.Secure;
                 Users.Add(de);
             }
         }
 
         return Users;
    }
    public override void ChangeUserProperty(dynamic User, CatalogProperty[] Props)
    {
        foreach(CatalogProperty CP in Props)
        { 
            (User as DirectoryEntry).Properties[CP.Property].Clear();
            (User as DirectoryEntry).Properties[CP.Property].Add(CP.Value); 
            (User as DirectoryEntry).CommitChanges();
        } 
    }
    public override dynamic FindUser(CatalogProperty[] Props,bool OneEnough)
    {
        return null;
    }
    public override List<dynamic> FindUsers(CatalogProperty[] Props,bool OneEnough)
    { 
        List<object> ResultList = new List<object>();
      foreach(DirectoryEntry obj in Users)
      {
          bool isMatch = !OneEnough;
          foreach (CatalogProperty CP in Props)
          {
              if(OneEnough==true)
              {
                  if ((obj as DirectoryEntry).Properties[CP.Property].Value == CP.Value)
                  {
                      isMatch = true;
                      break;
                  }
              }
              else
              {
                  if ((obj as DirectoryEntry).Properties[CP.Property].Value != CP.Value)
                  {
                      isMatch = false;
                      break;
                  }
              } 
          }
          if(isMatch)
          {
              ResultList.Add(obj); 
          }
      }
      return ResultList;
    }
    public override string CreateUser(CatalogProperty[] Props)
    {
        return "NotImplemented";
    }

    public override bool ChangePassword(dynamic User, string Password)
    {

        User.Invoke("SetPassword", new object[] { Password });
        User.Properties["LockOutTime"].Value = 0; //unlock account

        User.CommitChanges();
        return false;
    }
    /* 

      DirectoryEntry adEntry = null;
    private void SetADInfoAndCredentials()
    {
        adEntry = new DirectoryEntry("LDAP://" + ad_textBox.Text);
        adEntry.Username = user_textBox.Text;
        adEntry.Password = pw_textBox.Text;
    }

    private void SearchForMailInAD()
    {
        DirectorySearcher adSearcher = new DirectorySearcher(adEntry);
        adSearcher.Filter = ("mail=" + mail_textBox.Text);
        SearchResultCollection coll = adSearcher.FindAll();
        foreach (SearchResult item in coll)
        {
            foundUsers_listBox.Items.Add(item.GetDirectoryEntry());
        }
    }
     * 
public static void ChangePassword(string userID, string oldPassword, string newPassword)
        {           
            DirectoryEntry userEntry = Functions.GetUserEntry(userID);
            if (userEntry != null)
            {
                try
                {
                    // Check old password
                    // string userName = userEntry.Properties["CN"][0].ToString();
                    // DirectoryEntry en = new DirectoryEntry(userEntry.Path, userName, oldPassword, AuthenticationTypes.Secure);
                    // string cn = en.Properties["CN"][0].ToString();

                    userEntry.UsePropertyCache = true;
                    userEntry.Invoke("ChangePassword", new object[] { oldPassword, newPassword });
                    // userEntry.Invoke("SetPassword", new object[] { oldPassword });
                    userEntry.CommitChanges();
                    userEntry.Close();
                }
                catch (Exception e)
                {
                    Exception baseException = e.GetBaseException();
                    if (baseException is COMException)
                    {
                        COMException comException = baseException as COMException;
                        switch (comException.ErrorCode)
                        {
                            case -2147024810:
                                throw new Exception("The current password does not match our records. Please try again.");
                            case -2147022651:
                                throw new Exception("indicating password does not meet security requirements of the domain.");
                            case -2147023570:
                                throw new Exception("invalidate user or password.");
                            case -2147016657:
                                throw new Exception("invalidate user or password. Please try again. ");
                            default:
                                throw e;
                        }
                    }
                }
            }
            else
            {
                throw new Exception("UserID = '" + userID + "' not found");
            }
        }

        public static DirectoryEntry GetUserEntry(string userID)
        {
            DirectoryEntry entry = Environment.GetDirectoryEntry();
            string filter = "(&(objectClass=user)(Pager=" + userID + "))";
            DirectorySearcher search = new DirectorySearcher(entry, filter);
            search.SearchScope = SearchScope.Subtree;
            SearchResult result = search.FindOne();

            if (result != null)
            {
                DirectoryEntry userEntry = new DirectoryEntry(result.Path, Environment.AD_AdminAccountName, Environment.AD_AdminPassword, AuthenticationTypes.Secure);
                return userEntry;
            }
            else
            {
                return null;
            }
        }*/
}